package com.adee.netty.client;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 一、原始linux socket服务端程序（bio方式）：
 * int    socket_fd, connect_fd;
 *     struct sockaddr_in     servaddr;
 *     char    buff[4096];
 *     int     n;
 *     //初始化Socket
 *     if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
 *     printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
 *     exit(0);
 *     }
 *     //初始化
 *     memset(&servaddr, 0, sizeof(servaddr));
 *     servaddr.sin_family = AF_INET;
 *     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。
 *     servaddr.sin_port = htons(DEFAULT_PORT);//设置的端口为DEFAULT_PORT
 *
 *     //将本地地址绑定到所创建的套接字上
 *     if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
 *     printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
 *     exit(0);
 *     }
 *     //开始监听是否有客户端连接
 *     if( listen(socket_fd, 10) == -1){
 *     printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
 *     exit(0);
 *     }
 *     printf("======waiting for client's request======\n");
 *     while(1){
 * //阻塞直到有客户端连接，不然多浪费CPU资源。
 *         if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){
 *         printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
 *         continue;
 *     }
 * //接受客户端传过来的数据
 *     n = recv(connect_fd, buff, MAXLINE, 0);
 * //向客户端发送回应数据
 *     if(!fork()){
 *         if(send(connect_fd, "Hello,you are connected!\n", 26,0) == -1)
 *         perror("send error");
 *         close(connect_fd);
 *         exit(0);
 *     }
 *     buff[n] = '\0';
 *     printf("recv msg from client: %s\n", buff);
 *     close(connect_fd);
 *     }
 *     close(socket_fd);
 *
 * 二、java socket服务端程序
 *
 */
public class ServerSocketTest {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            //1、创建服务端的ServerSocket，指明自己的端口号
            //调用了linux中socket()+bind()+listen()
            serverSocket = new ServerSocket(2022);

            //2、调用accept接收到来自于客户端的socket
            //调用了linux中的accept()函数，返回的socket就是linux中的connect_fd
            socket = serverSocket.accept();//阻塞式监听，会一直等待客户端的接入，接入了之后才会显示消息

            //3、获取socket的输入流
            // InputStream/OutputStream底层持有linux中的connect_fd，通过connect_fd完成字节流的读写
            is = socket.getInputStream();


            //4、读取输入流中的数据
            //ByteArrayOutputStream的好处是它可以根据数据的大小自动扩充
            baos = new ByteArrayOutputStream();
            int len=0;
            byte[] buffer = new byte[1024];

            //判断是否将客户端发的消息读完了
            while ((len=is.read(buffer))!=-1){
                baos.write(buffer,0,len);
            }
            System.out.println("收到了来自于客户端"+
                    socket.getInetAddress().getHostName()
                    +"的消息："+baos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//5、关闭资源
            if(serverSocket!=null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(baos!=null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
